﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web;
using System.Web.Services;
using System.ServiceModel.Description;
using System.Web.Services.Protocols;
using System.Net;
using System.ServiceModel;
using Email_Attachment_Sharepoint_Movement;
using System.Configuration;
using Microsoft.Xrm.Sdk.Client;
using Microsoft.Xrm.Sdk;
using Microsoft.Xrm.Sdk.Query;
using Microsoft.Xrm.Sdk.Discovery;
using Microsoft.Xrm.Sdk.Messages;
using Microsoft.Xrm;
using Microsoft.Crm.Sdk.Messages;
using Microsoft.Crm.Sdk;
using Email_Attachment_Sharepoint_Movement.SPCopyService;
using Email_Attachment_Sharepoint_Movement.SPService;

namespace Email_Attachment_Sharepoint_Movement
{
   class Archieve_Attachments
   {

        #region Global Variable Initializing
        private IOrganizationService service = null;
        private SPService.Dws SPService = null;
        private SPCopyService.Copy SPCopyService = null;
        RetrieveMultipleResponse EmRes = null;
        RetrieveMultipleResponse MultiReponse = null;
        CopyResult copyResult = null; 
        #endregion

        public void ExecuteAttachmentArchieval()
        {
            try
            {
                InitializeSPCopyService();
                InitializeSPService();
                InitializeCRMService();
                RetrieveEmail(service);
                EntityCollection EmailCollection = EmRes.EntityCollection;
                foreach (Entity Email in EmailCollection.Entities)
                {
                    Guid Emailid = new Guid(Email.Attributes["activityid"].ToString());
                    string Foldername = ConfigurationManager.AppSettings["SP_LibraryName"].ToString() + "/" + Emailid.ToString();
                    CreateSharepointFolder(Foldername);
                    RetrieveAttachment(Emailid, service);
                    EntityCollection EmailAttachment =MultiReponse.EntityCollection;
                    foreach (Entity Attachment in EmailAttachment.Entities)
                    {
                        string OutputFilename = CleanInvalidCharacters(Attachment.Attributes["filename"].ToString());
                        byte[] filecount = Convert.FromBase64String(Attachment.Attributes["body"].ToString());
                        Guid attachmentId = new Guid(Attachment.Attributes["activitymimeattachmentid"].ToString());
                        UploadDocument(Foldername, OutputFilename, filecount);
                        if (copyResult.ErrorCode == CopyErrorCode.Success)
                        {
                            service.Delete("activitymimeattachment", attachmentId);
                            Console.WriteLine("Attachment Deleted: {0}", attachmentId);
                        }
                        else
                        {
                            Console.WriteLine("Copy Error: {0}", copyResult.ErrorMessage);
                            throw new InvalidOperationException(copyResult.ErrorMessage);
                        }
                    }
                }
            }
            catch (Exception ex)
                {
                    Console.WriteLine(" Error Occured: {0}",ex.Message);  
                }
        }

        private void InitializeCRMService()
        {
            try
            {
                ClientCredentials cred = new ClientCredentials();
                cred.UserName.UserName = ConfigurationManager.AppSettings["CRM_UserName"].ToString();
                cred.UserName.Password = ConfigurationManager.AppSettings["CRM_Password"].ToString();
                string OrgURL = ConfigurationManager.AppSettings["CRM_URL"].ToString() + "/XRMServices/2011/Organization.svc";
                Uri OrganizationUri = new Uri(OrgURL);
                Uri HomeRealmUri = null;
                OrganizationServiceProxy serviceProxy = new OrganizationServiceProxy(OrganizationUri, HomeRealmUri, cred, null);
                CrmAuthenticationToken token = new CrmAuthenticationToken();
                token.AuthenticationType = 1;
                token.OrganizationName = ConfigurationManager.AppSettings["CRM_OrgName"].ToString();

                serviceProxy.Authenticate();
                service = (IOrganizationService)serviceProxy;
                Console.WriteLine("CRM Service Initialized");
            }
            catch (Exception ex)
            {
                Console.WriteLine("CRM Serivce Initialization failed :" + ex.Message);
            }
         }

        private void InitializeSPService()
        {
            try
            {
                string SP_User = ConfigurationManager.AppSettings["SP_UserName"].ToString();
                string SP_Password = ConfigurationManager.AppSettings["SP_Password"].ToString();
                string SP_Domain = ConfigurationManager.AppSettings["SP_Domain"].ToString();
                string SP_URL = ConfigurationManager.AppSettings["SP_Server_URL"].ToString() + "_vti_bin/dws.asmx";
                SPService = new Dws();
                SPService.Url = SP_URL.ToString();
                SPService.UseDefaultCredentials = false;
                SPService.Credentials = new NetworkCredential(SP_User, SP_Password, SP_Domain);
                SPService.PreAuthenticate = true;
                SPService.UnsafeAuthenticatedConnectionSharing = true;
                SPService.InitializeLifetimeService();
                Console.WriteLine("Sharepoint URL Service Initialized");
            }
            catch (Exception ex)
            {
                Console.WriteLine("Error Occured while initializing Sharepoint Dws Service: {0}", ex.Message);
            }
        }

        private void InitializeSPCopyService()
        {
            try
            {
                string SP_User = ConfigurationManager.AppSettings["SP_UserName"].ToString();
                string SP_Password = ConfigurationManager.AppSettings["SP_Password"].ToString();
                string SP_Domain = ConfigurationManager.AppSettings["SP_Domain"].ToString();
                string SP_URL = ConfigurationManager.AppSettings["SP_Server_URL"].ToString() + "_vti_bin/Copy.asmx";
                SPCopyService = new Copy();
                SPCopyService.Url = SP_URL.ToString();
                SPCopyService.UseDefaultCredentials = false;
                SPCopyService.Credentials = new NetworkCredential(SP_User, SP_Password, SP_Domain);
                SPCopyService.PreAuthenticate = true;
                SPCopyService.UnsafeAuthenticatedConnectionSharing = true;
                SPCopyService.InitializeLifetimeService();
                Console.WriteLine("Sharepoint Copy Service Initialized");
            }
            catch (Exception ex)
            {
                Console.WriteLine("Error Occured while initializing Share Point Copy service: {0}", ex.Message);
            }
        }

        private void RetrieveEmail(IOrganizationService Iservice)
        {
            try
            {
                ConditionExpression cond1 = new ConditionExpression("createdon", ConditionOperator.OnOrBefore, DateTime.Now);
                ColumnSet EmailColSet = new ColumnSet(new string[] { "activityid","createdon" });
                QueryExpression EmailQuery = new QueryExpression("email");
                EmailQuery.ColumnSet = EmailColSet;
                EmailQuery.Criteria.AddCondition(cond1);
                RetrieveMultipleRequest EmReq = new RetrieveMultipleRequest();
                EmReq.Query = EmailQuery;
                EmRes = (RetrieveMultipleResponse)service.Execute(EmReq);
                //return EmRes.EntityCollection;
            }
            catch (Exception ex)
            {
                Console.WriteLine("Error occurred while retrieving Email: {0}", ex.Message);
            }
        }

        private void RetrieveAttachment(Guid Activityid, IOrganizationService Iservice)
        {
            try
            {
                ConditionExpression cond1 = new ConditionExpression("activityid", ConditionOperator.Equal, Activityid);

                ColumnSet Colset = new ColumnSet(new string[] { "filename", "body", "activitymimeattachmentid" });

                QueryExpression query = new QueryExpression("activitymimeattachment");
                query.Criteria.AddCondition(cond1);
                query.ColumnSet = Colset;

                RetrieveMultipleRequest RetrieveMulti = new RetrieveMultipleRequest();
                RetrieveMulti.Query = query;
                MultiReponse = (RetrieveMultipleResponse)Iservice.Execute(RetrieveMulti);
                //return MultiReponse.EntityCollection;
            }
            catch(Exception ex)
            {
                Console.WriteLine("Error occured while retrieving Attachment: {0}", ex.Message);
                
            }
        }

        private void CreateSharepointFolder(string Foldername)
        {
            try
            {

                string Result = SPService.CreateFolder(Foldername);
                if (Result.Equals("<Result/>"))
                {
                    Console.WriteLine("Folder '{0}' Created", Foldername);
                }
                else if (Result.Contains("AlreadyExist"))
                {
                    Console.WriteLine("Folder Already exist");
                }
                else
                {
                    Console.WriteLine(Result);
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine("Error occured while creating Sharepoint Folder: {0}", ex.Message);
            }

        }

        private void UploadDocument(string Foldername, string Filename, byte[] fileContent)
        {

            
            try
            {
                string[] destinationUrls = { ConfigurationManager.AppSettings["SP_Server_URL"].ToString() + Foldername + "/" + Filename };
                CopyResult[] result;
                FieldInformation Field = new FieldInformation();
                Field.DisplayName = Filename.Split('.')[0].ToString();
                Field.InternalName = "Attachment";
                Field.Type = FieldType.Attachments;
                Field.Value = "Attachments ";
                FieldInformation[] f1 = { Field };

                SPCopyService.CopyIntoItems("http://null", destinationUrls, f1, fileContent, out result);
                copyResult = result[0];
            }
            catch (Exception ex)
            {
                Console.WriteLine("Error Occured while Copying file to folder: {0}", ex.Message);
            }
        }

        public static string CleanInvalidCharacters(string name)
        {
            string cleanName = name;

            // remove invalid characters    
            cleanName = cleanName.Trim();
            cleanName = cleanName.Replace(@"#", string.Empty);
            cleanName = cleanName.Replace(@"%", string.Empty);
            cleanName = cleanName.Replace(@"&", string.Empty);
            cleanName = cleanName.Replace(@"*", string.Empty);
            cleanName = cleanName.Replace(@":", string.Empty);
            cleanName = cleanName.Replace(@"<", string.Empty);
            cleanName = cleanName.Replace(@">", string.Empty);
            cleanName = cleanName.Replace(@"?", string.Empty);
            cleanName = cleanName.Replace(@"\", string.Empty);
            cleanName = cleanName.Replace(@"/", string.Empty);
            cleanName = cleanName.Replace(@"{", string.Empty);
            cleanName = cleanName.Replace(@"}", string.Empty);
            cleanName = cleanName.Replace(@"|", string.Empty);
            cleanName = cleanName.Replace(@"~", string.Empty);
            cleanName = cleanName.Replace(@"+", string.Empty);
            cleanName = cleanName.Replace(@"-", string.Empty);
            cleanName = cleanName.Replace(@",", string.Empty);
            cleanName = cleanName.Replace(@"(", string.Empty);
            cleanName = cleanName.Replace(@")", string.Empty);

            //remove periods 
            while (cleanName.Contains(".."))
            {
                cleanName = cleanName.Replace(@"..", @".");
            }
            if (cleanName.Length > 50)
            {
                int len = cleanName.Length;
                cleanName = cleanName.Substring((len - 50), 50);
            }

            //remove invalid start character 
            if (cleanName.StartsWith("."))
            {
                cleanName = cleanName.Substring(1);
            }
            if (cleanName.EndsWith("."))
            {
                cleanName = cleanName.TrimEnd(new char[] { '.' });
            }

            if (cleanName.StartsWith("_"))
            {
                cleanName = cleanName.Substring(1);
            }
            return cleanName;
        }
    }
    
}
